package yxy.game.pm2.module.soloride;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.TypeReference;
import org.joda.time.DateTime;

import org.redisson.api.RMap;
import yxy.cherry.battle.module.Position;
import yxy.cherry.battle.module.record.FighterPosition;
import yxy.cherry.battle.module.record.FighterSide;
import yxy.cherry.battle.module.record.result.BattleResult;
import yxy.cherry.battle.module.record.result.StatisticFighter;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.soloride;
import yxy.cherry.game.base.redis.RedisManager;
import yxy.cherry.game.base.redis.RedisType;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.Hero;
import yxy.game.pm2.bean.PlayerBean;
import yxy.game.pm2.bean.currency.Currencies;
import yxy.game.pm2.message.SoloRideMessage;
import yxy.game.pm2.module.CurrencyHandle;
import yxy.game.pm2.module.battle.*;
import yxy.game.pm2.module.battle.FighterModule.InitHpLossRatio;

public class SoloRideHandle extends BattleModuleHandle {

    final public static int battleExpireDay = 2;// 战斗数据过期时间（天）

    static public enum BattleState {
        没有在战斗, 局间选将, 局中战斗, 战斗结算;
    }

    @Override
    protected String code() {
        return BattleType.SOLORIDE.name();
    }

    static public String battleCode(int index) {
        return String.format("%s:%s", BattleType.SOLORIDE.name(), index);
    }

    /**
     * 轮间间隔
     */
    static public int minuteRestPeriod() {
        return 10;
    }

    /**
     * 每轮局数
     */
    static public int roundPerPeriod() {
        return 10;
    }

    /**
     * 战斗执行
     */
    public Collection<SoloRideMessage.SoloRideBattle> battleResponseExecute(String playerCode, Hero hero) {
        int[] angersTeamA = null;

        FighterModule fighterModule = new BattleHandle().fighter(playerCode, hero, null);

        SoloRideHero soloRideHero = new SoloRideHero();
        soloRideHero.setCode(hero.getCode());
        soloRideHero.setHeroHp(10000);
        soloRideHero.setPower(new BattleHandle().power(playerCode, hero));
        soloRideHero.setFighterModule(fighterModule);

        SoloRideModule soloRideModule = SoloRideModule.get(playerCode);
        soloRideModule.setHero(soloRideHero);
        soloRideModule.set();

        return battleResponseExecute(playerCode, angersTeamA, DateTime.now(), soloRideModule);
    }

    /**
     * 附加怒气值的战斗执行方法
     */
    public Collection<SoloRideMessage.SoloRideBattle> battleResponseExecute(String playerCode, int[] angersTeamA, DateTime startTime,
                                                                            SoloRideModule soloRideModule) {
        ArrayList<SoloRideMessage.SoloRideBattle> resps = new ArrayList<>();

        SoloRideEntry soloRideEntry = new SoloRideEntry(soloRideModule);
        soloRideEntry.getBattleModules().clear();

        int stage = soloRideEntry.getStage() + 1;
        BattleModule battleModule = createBattleModule(soloRideEntry, stage, 0);

        soloRideEntry.getBattleModules().add(battleModule);
        soloRideEntry.setBattling(true);

        new SoloRideHandle().battle(playerCode, angersTeamA, startTime, soloRideEntry);

        BattleHandle battleHandle = new BattleHandle();
        CurrencyHandle currencyHandle = new CurrencyHandle();
        for (BattleModule battle : soloRideEntry.getBattleModules()) {
            SoloRideMessage.SoloRideBattle.Builder builder = SoloRideMessage.SoloRideBattle.newBuilder();
            builder.setPlayback(battleHandle.playback(battle));// , team_a, team_b));
            builder.addAllRewards(currencyHandle.packItems(battle.getSettlement().reward()));
            resps.add(builder.build());
        }

        soloRideModule = soloRideEntry.resetModule(soloRideModule);
        soloRideModule.set();

        return resps;
    }

    public void battle(String playerCode, int[] angersTeamA, DateTime startTime, SoloRideEntry soloRideEntry) {
        int rounds = roundPerPeriod();
        int stage = soloRideEntry.getStage() + 1;
        soloRideEntry.getHero().setHeroHp(10000);

        BattleModule battleModule = null;
        if (soloRideEntry.getBattleModules().size() > 0) {
            battleModule = soloRideEntry.getBattleModules().getFirst();
        } else {
            battleModule = createBattleModule(soloRideEntry, stage, 0);
        }
        initSettlementRewards(soloRideEntry, battleModule);

        BattleHandle battleHandle = new BattleHandle();
        for (int i = 1; i <= rounds; i++) {
            System.err.println("战斗 stage:::	" + stage);
            battleHandle.battleResponseExecute(battleModule, BattleHandle.defaultBattleRoundLimit, false, angersTeamA, null);

            saveHp(playerCode, soloRideEntry, battleModule);// 缓存血量
            battleModule.timeline().setStartTime(startTime);
            battleModule.time();

            if (!battleModule.getBattleResult().equals(BattleResult.LEFT_WIN)) {
                break;
            }
            soloRideEntry.getRewards().clear();
            soloRideEntry.getRewards().addAll(Currency.merge(battleModule.getSettlement().reward()));
            if (i == rounds) {
                break;
            }
            stage++;
            soloride data = DataCenter.getData(stage, soloride.class);
            if (data == null) {
                // 已经完成最后一关
                break;
            }
            soloRideEntry.setStage(stage);
            angersTeamA = cacheAnger(battleModule, FighterSide.LEFT);// 缓存怒气
            startTime = battleModule.timeline().getEndTime();
            battleModule = createBattleModule(soloRideEntry, stage, i);
            initSettlementRewards(soloRideEntry, battleModule);
            soloRideEntry.getBattleModules().add(battleModule);
        }
        soloRideEntry.setStage(stage);
    }

    private void initSettlementRewards(SoloRideEntry soloRideEntry, BattleModule battleModule) {
        SettlementSoloRide settlement = (SettlementSoloRide) battleModule.getSettlement();
        int stage = settlement.getStage() - 1;
        if (stage > soloRideEntry.getToday() && stage > soloRideEntry.getStart()) {
            soloride data = DataCenter.getData(stage, soloride.class);
            if (data == null) {
                return;
            }
            Collection<Currency> rewards = Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum());
            settlement.getRewards().addAll(soloRideEntry.getRewards());
//			System.err.println("BB::" + settlement.getRewards());
            settlement.getRewards().addAll(rewards);
//			System.err.println("BC::" + settlement.getRewards());
        }
    }

    private BattleModule createBattleModule(SoloRideEntry soloRideEntry, int stage, int index) {
        String playerCode = soloRideEntry.getPlayerCode();

        if (soloRideEntry.getHero() == null) {
            return null;
        }

        BattleModule battleModule = BattleModule.create(playerCode);
        battleModule.setType(BattleType.SOLORIDE);
        battleModule.setCode(battleCode(index));

        // 玩家的team
        TeamModule teamA = teamPlayer(playerCode, soloRideEntry.getHero());
        battleModule.setTeamA(teamA);

        // 征战地图
        TeamModule teamB = teamSoloRide(stage);
        battleModule.setTeamB(teamB);

        battleModule.setSettlement(SettlementSoloRide.create(playerCode, stage));

        return battleModule;
    }

    private TeamModule teamPlayer(String playerCode, SoloRideHero hero) {
        TeamModule team = new TeamModule();
        FighterModule heroModule = hero.getFighterModule();
        Hero heroBean = Hero.get(playerCode, hero.getCode());
        FighterModule fighterModule = new BattleHandle().fighter(playerCode, heroBean, null);
        fighterModule.setAnger(heroModule.getAnger());
        fighterModule.setProperty(heroModule.getProperty());
        fighterModule.setInitHp(new InitHpLossRatio(hero.getHeroHp()));

        team.addfighter(Position.FM, fighterModule);
        // 信息
        PlayerBean playerBean = PlayerBean.get(playerCode);
        team.setName(playerBean.getName());
        team.setHead(playerBean.getHead());
        team.setLevel(playerBean.getLevel());
        team.setPower(team.power());

        return team;
    }

    public TeamModule teamSoloRide(int stage) {
        TeamModule team = new TeamModule();
        soloride mapdata = DataCenter.getData(stage, soloride.class);

        RMap<String, ArrayList<FighterModule>> rMap = RedisManager.getInstance().getConnection(RedisType.REDIS_DATA).client().getMap("INIT:soloride");
        JSONArray arrary = (JSONArray) JSONArray.toJSON(rMap.get(String.valueOf(stage)));
        ArrayList<FighterModule> fighterModules = JSON.parseObject(arrary.toString(), new TypeReference<ArrayList<FighterModule>>() {
        });
        // 武将
        for (int i = 0; i < mapdata.getHeroid().length; i++) {
            Position position = Position.forValue(i + 1);
            int heroid = mapdata.getHeroid()[i];
            if (heroid == -1) continue;
            FighterModule fighterModule = fighterModules.get(i);
            team.addfighter(position, fighterModule);
        }
        // 神器
//		WeaponModule weapon = WeaponModule.create(mapdata.getWeapondataid(), mapdata.getWeaponlv(), 0, 0, mapdata.getWeaponskilllv());
//		team.setWeapon(weapon);

        // 信息
        team.setName(mapdata.getName());
        team.setHead(mapdata.getHeadid());
        team.setPower(team.power());

        return team;
    }

    private void saveHp(String playerCode, SoloRideEntry soloRideEntry, BattleModule battleModule) {
        for (StatisticFighter fighter : battleModule.getStatistics()) {
            if (!fighter.getPos().equals(FighterPosition.FML)) {
                continue;
            }
            int ratio = (int) (fighter.getHpc() * 10000 / fighter.getHpu());
            if (ratio < 10000) {
                soloRideEntry.getHero().setHeroHp(ratio);
            }
        }
    }

    private int[] cacheAnger(BattleModule battleModule, FighterSide fighterSide) {
        int[] angers = new int[7];
        for (StatisticFighter fighter : battleModule.getStatistics()) {
            if (!fighter.getPos().getSide().equals(fighterSide)) {
                continue;
            }
            FighterPosition fp = fighter.getPos();
            if (fp.equals(FighterPosition.NBL) || fp.equals(FighterPosition.NBR)) {
                angers[0] = fighter.getAng();
                continue;
            }
            if (fp.equals(FighterPosition.SSL) || fp.equals(FighterPosition.SSR)) {
                angers[0] = fighter.getAng();
                continue;
            }
            angers[fp.getPosition().getValue()] = fighter.getAng();
        }
        return angers;
    }

    /**
     * 终战结算
     */
    public void settleStage(String playerCode, int stage) {
        SoloRideModule soloRideModule = SoloRideModule.get(playerCode);

        soloRideModule.pass(stage - 1);

        soloRideModule.setBattling(false);
        soloRideModule.getBattles().clear();
        soloRideModule.getRewards().clear();
        soloRideModule.setCurrent(0);

        soloRideModule.setHero(null);

        soloRideModule.set();
    }

    static public class SoloRideEntry {
        private String playerCode;

        private int today;// 今日最高通关
        private int start;// 今日起始关卡

        private int stage;// 当前关卡

        private boolean battling;
        private LinkedList<BattleModule> battleModules = new LinkedList<>();
        private SoloRideHero hero;// 武将
        private int heroHp;// 武将损失血量万分比
        private Currencies rewards = new Currencies();
        private DateTime tickTime;

        private BattleModule settleBattle;

        public SoloRideEntry(SoloRideModule soloRideModule) {
            this.playerCode = soloRideModule.getPlayerCode();
            this.battling = soloRideModule.isBattling();
            this.tickTime = soloRideModule.getTickTime();
            this.today = soloRideModule.getToday();
            this.start = soloRideModule.getStart();
            if (soloRideModule.getCurrent() <= 0) {
                this.stage = this.start - 1;
            } else {
                this.stage = soloRideModule.getCurrent();
            }
            this.hero = soloRideModule.getHero();
            this.rewards.addAll(soloRideModule.getRewards());
            for (String battleCode : soloRideModule.getBattles()) {
                BattleModule battleModule = BattleModule.get(playerCode, battleCode);
                this.battleModules.add(battleModule);
            }
        }

        public SoloRideModule resetModule(SoloRideModule soloRideModule) {
            soloRideModule.getBattles().clear();
            for (BattleModule battleModule : getBattleModules()) {
                battleModule.set(battleExpireDay);
                soloRideModule.getBattles().add(battleModule.getCode());
            }
            soloRideModule.setRewards(getRewards());
            soloRideModule.setBattling(isBattling());
            soloRideModule.setCurrent(getStage());

            return soloRideModule;
        }

        public String getPlayerCode() {
            return playerCode;
        }

        public void setBattling(boolean battling) {
            this.battling = battling;
        }

        public boolean isBattling() {
            return battling;
        }

        public void setStage(int stage) {
            this.stage = stage;
        }

        public int getStage() {
            return stage;
        }

        public int getToday() {
            return today;
        }

        public int getStart() {
            return start;
        }

        public void setBattleModules(LinkedList<BattleModule> battleModules) {
            this.battleModules = battleModules;
        }

        public LinkedList<BattleModule> getBattleModules() {
            return battleModules;
        }

        public void setSettleBattle(BattleModule settleBattle) {
            this.settleBattle = settleBattle;
        }

        public BattleModule getSettleBattle() {
            return settleBattle;
        }

        public SoloRideHero getHero() {
            return hero;
        }

        public int getHeroHp() {
            return heroHp;
        }

        public Currencies getRewards() {
            return rewards;
        }

        public DateTime getTickTime() {
            return tickTime;
        }

        public BattleModule getLastBattle() {
            return getBattleModules().getLast();
        }

    }

}
